using System;
using System.Collections;
using System.IO;
using System.Text;
using Commons.Collections;
using Neo.Generator.Core;
using NVelocity;
using NVelocity.App;

namespace Webbness.Module.VsTool
{
    [Serializable]
    public abstract class BaseTemplateCreator
    {
        protected ArrayList _createdFiles = new ArrayList();
        protected bool _createFolders;
        protected bool _forceOverwrite;
        protected string _outputRoot;
        protected string _projectName;
        protected string _template;
        protected string _templatesFolder;

        protected void Generate(string templateName, GenerationContext context, TextWriter writer)
        {
            VelocityEngine ve = new VelocityEngine();
            ExtendedProperties ep = new ExtendedProperties();
            ep.SetProperty("file.resource.loader.path", _templatesFolder);
            ep.SetProperty("runtime.log.error.stacktrace", "true");
            ep.SetProperty("runtime.log.warn.stacktrace", "true");
            ep.SetProperty("runtime.log.info.stacktrace", "true");
            ep.SetProperty("runtime.introspector.uberspect", "NVelocity.Util.Introspection.UberspectImpl");
            ep.SetProperty("directive.manager", "NVelocity.Runtime.Directive.DirectiveManager; NVelocity");
            ve.Init(ep);
            Template template = ve.GetTemplate(templateName);
            VelocityContext velocityContext = new VelocityContext();
            velocityContext.Put("Rails", context);
            velocityContext.Put("Neo", context);
            velocityContext.Put("HtmlHelpers", new HtmlHelpers());
            velocityContext.Put("ThisTemplateName", templateName);
            template.Merge(velocityContext, writer);
        }

        protected void Generate(string templateName, TextWriter writer, params ContextItem[] contextItems)
        {
            VelocityEngine ve = new VelocityEngine();
            ExtendedProperties ep = new ExtendedProperties();
            ep.SetProperty("file.resource.loader.path", _templatesFolder);
            ep.SetProperty("runtime.log.error.stacktrace", "true");
            ep.SetProperty("runtime.log.warn.stacktrace", "true");
            ep.SetProperty("runtime.log.info.stacktrace", "true");
            ep.SetProperty("runtime.introspector.uberspect", "NVelocity.Util.Introspection.UberspectImpl");
            ep.SetProperty("directive.manager", "NVelocity.Runtime.Directive.DirectiveManager; NVelocity");
            ve.Init(ep);
            Template template = ve.GetTemplate(templateName);
            VelocityContext velocityContext = new VelocityContext();
            foreach (ContextItem item in contextItems)
            {
                velocityContext.Put(item.Name, item.Item);
            }
            velocityContext.Put("ThisTemplateName", templateName);
            template.Merge(velocityContext, writer);
        }

        protected void Generate(string templatePath, string templateName, GenerationContext context, TextWriter writer)
        {
            VelocityEngine ve = new VelocityEngine();
            ExtendedProperties ep = new ExtendedProperties();
            ep.SetProperty("file.resource.loader.path", templatePath);
            ep.SetProperty("runtime.log.error.stacktrace", "true");
            ep.SetProperty("runtime.log.warn.stacktrace", "true");
            ep.SetProperty("runtime.log.info.stacktrace", "true");
            ep.SetProperty("runtime.introspector.uberspect", "NVelocity.Util.Introspection.UberspectImpl");
            ep.SetProperty("directive.manager", "NVelocity.Runtime.Directive.DirectiveManager; NVelocity");
            ve.Init(ep);
            Template template = ve.GetTemplate(templateName);
            VelocityContext velocityContext = new VelocityContext();
            velocityContext.Put("Rails", context);
            velocityContext.Put("Neo", context);
            velocityContext.Put("HtmlHelpers", new HtmlHelpers());
            velocityContext.Put("ThisTemplateName", templateName);
            template.Merge(velocityContext, writer);
        }

        protected void Generate(string templatePath, string templateName, TextWriter writer, params ContextItem[] contextItems)
        {
            VelocityEngine ve = new VelocityEngine();
            ExtendedProperties ep = new ExtendedProperties();
            ep.SetProperty("file.resource.loader.path", templatePath);
            ep.SetProperty("runtime.log.error.stacktrace", "true");
            ep.SetProperty("runtime.log.warn.stacktrace", "true");
            ep.SetProperty("runtime.log.info.stacktrace", "true");
            ep.SetProperty("runtime.introspector.uberspect", "NVelocity.Util.Introspection.UberspectImpl");
            ep.SetProperty("directive.manager", "NVelocity.Runtime.Directive.DirectiveManager; NVelocity");
            ve.Init(ep);
            Template template = ve.GetTemplate(templateName);
            VelocityContext velocityContext = new VelocityContext();
            foreach (ContextItem item in contextItems)
            {
                velocityContext.Put(item.Name, item.Item);
            }
            velocityContext.Put("ThisTemplateName", templateName);
            template.Merge(velocityContext, writer);
        }

        protected void GenerateOutputFromTemplate(string outputFile, string templateName, GenerationContext ctx, bool forceForEntity)
        {
            if (File.Exists(Path.Combine(_templatesFolder, templateName)) == false)
            {
                throw new FileNotFoundException(new StringBuilder("Template file not found: '").Append(templateName).Append("'").ToString(), templateName);
            }
            if (_forceOverwrite || (File.Exists(outputFile) == false) || forceForEntity)
            {
                Console.WriteLine(new StringBuilder("Writing ").Append(outputFile));
                using (StreamWriter writer = new StreamWriter(outputFile))
                {
                    Generate(templateName, ctx, writer);
                }
            }
        }

        protected void GenerateOutputFromTemplate(string outputFile, string templatePath, string templateName, GenerationContext ctx)
        {
            if (File.Exists(Path.Combine(templatePath, templateName)) == false)
            {
                throw new FileNotFoundException(new StringBuilder("Template file not found: '").Append(templateName).Append("'").ToString(), templateName);
            }
            if (_forceOverwrite || File.Exists(outputFile) == false)
            {
                Console.WriteLine(new StringBuilder("Writing ").Append(outputFile));
                using (StreamWriter writer = new StreamWriter(outputFile))
                {
                    Generate(templatePath, templateName, ctx, writer);
                }
            }
        }

        protected object iif(bool condition, object trueValue, object falseValue)
        {
            if (condition)
            {
                return trueValue;
            }
            return falseValue;
        }
    }
}